package network.server;

import logic.baselogic.Database;
import logic.messagelogic.IMessageHandler;
import logic.messagelogic.Message;
import logic.messagelogic.MessageHandler;
import network.message.IMessageReceiver;
import network.message.IMessageSender;
import network.message.SocketMessageReceiver;
import network.message.SocketMessageSender;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Main class providing connection.
 */

public class SocketServer implements IServer {
    //Static port to connect with client. The same value should be on the client side.
    private final static int port = 11223;
    private static Database database;
    private Thread workingThread;
    private SocketProcessor socketProcessor;

    public void up() {
        try {
            socketProcessor = new SocketProcessor(new ServerSocket(port));
            workingThread = new Thread(socketProcessor);
            workingThread.start();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    public void down() {
        database.saveBase();
        socketProcessor.stop();
        workingThread.stop();
    }


    private static class SocketProcessor implements Runnable {
        private ServerSocket socket;
        private static Socket connection;

        private SocketProcessor(ServerSocket socket) throws Throwable {
            this.socket = socket;
        }

        public void run() {
            IMessageHandler messageHandler = new MessageHandler();
            database = Database.initBase();
            int operationsCounter = 0;
            while (true) {
                //Trying to get connection:
                try {
                    connection = socket.accept();
                } catch (IOException e) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try {
                        connection = socket.accept();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }

                IMessageReceiver messageReceiver = new SocketMessageReceiver(connection);
                IMessageSender messageSender = new SocketMessageSender(connection);

                //Receiving message
                String message = messageReceiver.receiveMessage();

                String response = messageHandler.handleMessage(database, new Message(null, null, null));

                //Sending response:
                messageSender.sendMessage(response);

                operationsCounter++;
                if (operationsCounter == Database.MAX_NON_SAVED_TRANSACTIONS) {
                    operationsCounter = 0;
                    database.saveBase();
                }

            }

        }

        public void stop() {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
    }
}